use std::rc::Rc;

#[derive(Debug)]
enum list {
    Cons(i32, Box<list>),
    Nil,
}

#[derive(Debug)]
enum list2 {
    Cons(i32, std::rc::Rc<list2>),
    Nil,
}

#[test]
fn test_box() {
    let a = list::Cons(1, Box::new(list::Cons(2, Box::new(list::Nil))));
    println!("{:?}", a);

    let b = Rc::new(list2::Cons(5, std::rc::Rc::new(list2::Cons(10, std::rc::Rc::new(list2::Nil)))));
    let c = list2::Cons(3, Rc::clone(&b));
    let d = list2::Cons(4, b.clone());
    println!("{:?} {:?}", c,d);

}



#[test]
fn test_ref1() {
    let a = 10;
    let b = &a;
    let c = Box::new(a);
    assert_eq!(10,a);
    assert_eq!(10,*b);
    assert_eq!(10,*c);
}

struct JBox<T>(T,T);
impl<T> JBox<T> {
    fn new(x: T, y:T) -> JBox<T> {
        JBox(x,y)
    }
}

impl<T> std::ops::Deref for JBox<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.1
    }
}

impl<T> Drop for JBox<T> {
    fn drop(&mut self) {
        println!("Dropping JBox");
    }
}

#[test]
fn test_jbox() {
    let b = JBox::new(1,2);
    println!("{:?}",*b);
}

#[test]
fn test_un() {
    let mut a = 1;
    let b = &a as *const i32;
    let c = &mut a as *mut i32;
    unsafe {
        *c = 2;
        println!("{:?}",*c);
    }

}